export const defaultTimeout = 10; //全局接口超时秒数

declare interface AnyObject {
  [key: string]: any;
}

// 生成key值
export function generateKey(name: string, argument: AnyObject) {
  // 从arguments 中取得数据
  const params = JSON.stringify(argument);
  try {
    // 返回 字符串，接口url + 接口请求参数
    return `${name}:::${params}`;
  } catch (_) {
    // 返回生成key错误
    return new Error('生成缓存key错误');
  }
}



// 定义接口对象模型
class ItemCache {
  //当前接口所存储的data
  data: any;
  // 设定超时时间，设定为多少秒
  timeout: number;
  // 设置数据(创建接口模型)的时间 也就是当前接口的key所对应的data获得的时间
  createTime: number;
  constructor(data: any, timeout: number) {
    this.data = data; 
    this.timeout = timeout;
    this.createTime = new Date().getTime(); // 168956854502
  }
}


// 缓存池类
class CachePool {
  // 缓存池容器
  static pool = new Map<string, ItemCache>();  //map类型为{url: 接口模型, url: 接口模型, ...}

  // 数据是否超时 没有数据相当于超时 要获取新数据
  static isOverTime(key: string): boolean {
    // 从接口缓存池获取当前接口模型
    const itemCache = CachePool.pool.get(key);
    // 没有数据 一定超时
    if (!itemCache) return true;
    // 获取系统当前时间
    const currentTime = new Date().getTime();
    // 获取当前时间与存储时间的过去的秒数
    const overSecond = (currentTime - itemCache.createTime) / 1000;
    // 如果过去的秒数大于当前接口设置的超时时间，也返回null让其去服务端取数据
    if (Math.abs(overSecond) > itemCache.timeout) {
      // 此代码可以没有，不会出现问题，但是如果有此代码，再次进入该方法就可以减少判断。
      CachePool.pool.delete(key);
      return true;
    }
    // 不超时
    return false;
  }

  // 废弃代码---> 当前data在 cache 中是否超时
  // static has(name: string) {
  //   return !CachePool.isOverTime(name);
  // }

  // 删除 pool 中的 data
  static delete(key: string) {
    return CachePool.pool.delete(key);
  }

  // 从池子里拿数据 拿的是具体的数据
  static getCacheData(key: string) {
    const isDataOverTime = CachePool.isOverTime(key);
    //如果 数据超时，返回null，但是没有超时，返回数据，而不是 ItemCache 对象
    return isDataOverTime ? null : CachePool.pool.get(key)?.data;
  }

  // 设置数据 默认存储10秒
  static setCacheData(key: string, data: any, timeout = 10) {
    // 设置数据是map结构 所以不用判断是否存过key 直接覆盖旧数据
    // 设置每个接口模型 itemCache
    const itemCache = new ItemCache(data, timeout);
    //缓存进 接口模型
    CachePool.pool.set(key, itemCache);
  }
}

export { ItemCache, CachePool };
